package com.study.crypto.basic.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Songjin
 * @since 2021-01-10 15:10
 */
@Slf4j
public class HttpUtils {
    
    private static final PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager();
    private static final RequestConfig requestConfig;
    
    private HttpUtils() {
    }
    
    public static JSONObject doPost(String apiUrl, String request) throws IOException {
        try(CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(apiUrl);
            httpPost.setConfig(requestConfig);
            log.debug("request is {}", request);
            StringEntity stringEntity = new StringEntity(request, Consts.UTF_8);
            stringEntity.setContentType(ContentType.APPLICATION_JSON.toString());
            httpPost.setEntity(stringEntity);
            CloseableHttpResponse response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String responseText = EntityUtils.toString(entity, Consts.UTF_8);
            log.debug("http post request is {}", responseText);
            EntityUtils.consume(response.getEntity());
            return JSON.parseObject(responseText);
        }
    }
    
    public static String doPost(String apiUrl, Map<String, String> request) throws IOException {
        List<NameValuePair> parameters = new ArrayList<>();
        for (Map.Entry<String, String> entry : request.entrySet()) {
            parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        return doPost(apiUrl, parameters);
    }
    
    public static String doPost(String apiUrl, List<NameValuePair> parameters) throws IOException {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            return executeUrlEncodedFormEntity(apiUrl, httpClient, parameters);
        }
    }
    
    private static String executeUrlEncodedFormEntity(String apiUrl, CloseableHttpClient httpClient, List<NameValuePair> parameters) throws IOException {
        HttpPost httpPost = new HttpPost(apiUrl);
        UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(parameters, Consts.UTF_8);
        httpPost.setEntity(urlEncodedFormEntity);
        try(CloseableHttpResponse response = httpClient.execute(httpPost)) {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                return EntityUtils.toString(entity, Consts.UTF_8);
            }
            return StringUtils.EMPTY;
        }
    }
    
    static {
        connMgr.setMaxTotal(100);
        connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal());
        Builder configBuilder = RequestConfig.custom();
        configBuilder.setConnectTimeout(50000);
        configBuilder.setSocketTimeout(50000);
        configBuilder.setConnectionRequestTimeout(10000);
        configBuilder.setExpectContinueEnabled(true);
        requestConfig = configBuilder.build();
    }
}
